<?php

namespace paymch\models;

use Yii;
use common\models\trade\Trade;
use common\models\trade\HandleTrade;

/**
 * 关闭交易
 * AlipayForm is the model behind the alipay async notify form.
 * 
 * @author emhome <emhome@163.com>
 * @since 2.0
 */
class TradeClose extends BasePaymentModel {

    /**
     * 交易中心分配给商户的应用ID
     * @var string(16) 交易中心分配给商户的应用ID
     * @example 72300007148
     * @static 是
     */
    public $app_id;

    /**
     * 签名类型
     * @var string(10) 商户生成签名字符串所使用的签名算法类型，目前支持RSA2和RSA，推荐使用RSA2
     * @example RSA2
     * @static 是
     */
    public $sign_type;

    /**
     * 请求签名
     * @var string(256) 请参考异步返回结果的验签
     * @example 601510b7970e52cc63db0f44997cf70e
     * @static 是
     */
    public $sign;

    /**
     * 编码格式
     * @var string(10) 编码格式，如utf-8、gbk、gb2312等
     * @example utf-8
     * @static 是
     */
    public $charset;

    /**
     * 接口版本
     * @var string(3) 调用的接口版本，固定为：1.0
     * @example 1.0
     * @static 是
     */
    public $version;

    /**
     * 商家订单号
     * @var string(64) 外部商户订单号
     * @example 2013112011001004330000121536
     * @static 是
     */
    public $bizno;

    /**
     * 同步通知地址
     * @var string(256) 交易处理结束后返回对应的同步通知地址 http/https路径
     * @example 601510b7970e52cc63db0f44997cf70e
     * @static 否
     */
    public $return_url;
    private $_partner = null;
    private $_trades = null;

    /**
     * 交易中心统一下单请求参数校验
     * @inheritdoc
     */
    public function rules() {
        return [
            [['sign_type', 'sign', 'charset', 'version', 'app_id', 'bizno'], 'required'],
            [['sign_type', 'charset', 'version', 'app_id'], 'string', 'max' => 16],
            ['bizno', 'string', 'max' => 32],
            ['return_url', 'string', 'max' => 255],
            //校验APPID
            ['app_id', 'validateAppId'],
            //验证下单请求签名
            ['sign', 'validateSignature'],
            //验证商户订单号是否存在
            ['bizno', 'validateBizno'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'app_id' => '交易中心分配给商户的应用ID',
            'charset' => '编码格式',
            'version' => '接口版本',
            'sign_type' => '签名类型',
            'sign' => '签名',
            'bizno' => '商户业务号',
            'return_url' => '交易回调地址',
        ];
    }

    /**
     * Validates the APPID.
     * 验证app_id是否为该商户本身
     *
     * @param string $attribute the attribute currently being validated
     */
    public function validateAppId($attribute) {
        if (!$this->hasErrors()) {
            $partner = $this->getPartner();
            if (!$partner) {
                $this->addError($attribute, '未签约商户！');
            } else {
                $this->_partner = $partner;
            }
        }
    }

    /**
     * Validates the signature.
     * 校验请求的签名
     *
     * @param string $attribute the attribute currently being validated
     */
    public function validateSignature($attribute) {
        if (!$this->hasErrors()) {
            $paymchServer = new \common\components\paymch\MchServer([
                'appId' => $this->app_id,
                'version' => $this->version,
                'charset' => $this->charset,
                'rsaPublicKeyFilePath' => Yii::getAlias('@common') . '/data/keys/emchpay/rsa_public_key.pem',
            ]);
            $flag = $paymchServer->checkSignature($this->attributes, 'RSA2');
            if (!$flag) {
                $this->addError($attribute, '请求签名校验失败！');
            }
        }
    }

    /**
     * Validates the bizno.
     * 商户需要验证该通知数据中的bizno是否为商户系统中创建的订单号
     *
     * @param string $attribute the attribute currently being validated
     */
    public function validateBizno($attribute) {
        if (!$this->hasErrors()) {
            $trades = $this->getTrades();
            if (!$trades) {
                $this->addError($attribute, '交易不存在或者交易状态已变更！');
            } else {
                $this->_trades = $trades;
            }
        }
    }

    /**
     * Find Partner by [[appid]]
     *
     * @return \common\models\trade\Partner|null
     */
    protected function getPartner() {
        if ($this->_partner === null) {
            $this->_partner = \common\models\trade\Partner::findByAppId($this->app_id);
        }
        return $this->_partner;
    }

    /**
     * Find Partner by [[bizno]]
     *
     * @return \common\models\trade\Trade|null
     */
    protected function getTrades() {
        if ($this->_trades === null) {
            $this->_trades = Trade::find()
            ->where(['bizno' => $this->bizno])
            ->andWhere([
                'status' => [
                    Trade::STATUS_DEFAULT,
                    Trade::STATUS_WAITPAY
                ]
            ])
            ->all();
        }
        return $this->_trades;
    }

    /**
     * 关闭交易提交保存
     * @return bool whether the email was sent
     */
    public function save(&$msg) {
        if (!$this->validate()) {
            $msg = \common\helpers\Utils::arrayToString($this->firstErrors, false);
            return false;
        }
        //关闭当前外部订单号下的所有历史交易
        if (HandleTrade::closeByBizno($this->bizno, $msg) === false) {
            Yii::error('Bizno Order close error:' . $msg);
            return false;
        }
        return true;
    }

}
